use cortex_m_semihosting::{debug, hprintln};


#[derive(Debug, Clone, Copy, PartialEq)]
pub struct LosList {
	pub pst_prev: *mut LosList,
	pub pst_next: *mut LosList,
}

pub const fn null_mut() -> *mut LosList {
	0 as *mut LosList 
}

fn _list_add(new: *mut LosList, prev: *mut LosList, next: *mut LosList) {
    unsafe {
        (*next).pst_prev = new;
        (*new).pst_next = next;
        (*new).pst_prev = prev;
        (*prev).pst_next = new;
    }
}

fn _list_del(prev: *mut LosList, next: *mut LosList) {
    unsafe {
        (*next).pst_prev = prev;
        (*prev).pst_next = next;
    }
}

fn _list_del_entry(entry: &mut LosList) {
    _list_del(entry.pst_prev, entry.pst_next);
}

impl LosList {
	pub fn new() -> Self {
		let head = LosList {
			pst_prev:null_mut(),
			pst_next:null_mut(),
		};
		head
	}

	pub fn init(&mut self) {
		self.pst_prev = self;
		self.pst_next = self;
	}

	pub fn add(&mut self,node:&mut LosList){
		_list_add(node, self, self.pst_next);
	}

	pub fn add_tail(&mut self,new:&mut LosList){
		_list_add(new, self.pst_prev, self);
	}

	pub fn list_del(entry:&mut LosList){
		_list_del_entry(entry);
		entry.pst_prev = null_mut();
		entry.pst_next = null_mut();
	}

	pub fn next(&self ) -> &LosList {
		return unsafe {&*self.pst_next}
	}

	pub fn prev(&self ) -> &LosList {
		return unsafe {&*self.pst_prev}
	}

	pub fn first(&self ) -> &LosList {
		return unsafe {&*self.pst_next}
	}
	pub fn empty(entry:&mut LosList) -> bool {
		return entry.pst_next == entry.pst_prev
	}
}


pub fn test_list(){
    	//list test
	let list = &mut LosList::new();
	list.init();

	assert!(!list.pst_prev.is_null() && !list.pst_next.is_null());
	assert!(list.pst_prev == list.pst_next);
	
	list.add(&mut LosList::new());
	list.add_tail(&mut LosList::new());
	list.add(&mut LosList::new());
	list.add(&mut LosList::new());
	list.add_tail(&mut LosList::new());

	let mut current = list;
	let mut count = 10;
	hprintln!("list test! ").unwrap();
	while count > 0 {
		hprintln!("{:?} - {:?}", current, current.pst_next);
		current = unsafe {&mut *current.pst_next};
		count -= 1;
	}

}

/*
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        
    }
}*/